package com.next.service;

import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import com.next.beans.PageQuery;
import com.next.common.TrainSeatLevel;
import com.next.common.TrainType;
import com.next.common.TrainTypeSeatConstant;
import com.next.dao.TrainNumberDetailMapper;
import com.next.dao.TrainNumberMapper;
import com.next.exception.BusinessException;
import com.next.model.TrainNumber;
import com.next.model.TrainNumberDetail;
import com.next.model.TrainSeat;
import com.next.param.GenerateTicketParam;
import com.next.param.TrainSeatSearchParam;
import com.next.seatDao.TrainSeatMapper;
import com.next.util.BeanValidator;
import javafx.util.Pair;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
public class TrainSeatService {

    @Resource
    private TrainSeatMapper trainSeatMapper;
    @Resource
    private TrainNumberDetailMapper trainNumberDetailMapper;
    @Resource
    private TrainNumberMapper trainNumberMapper;

    public List<TrainSeat> searchList(TrainSeatSearchParam param, PageQuery pageQuery) {
        BeanValidator.check(param);
        BeanValidator.check(pageQuery);
        TrainNumber trainNumber = trainNumberMapper.findByName(param.getTrainNumber());
        if (trainNumber == null) {
            throw new BusinessException("待查询的车次不存在");
        }

        List<TrainSeat> seatList = trainSeatMapper.searchList(trainNumber.getId(), param.getTicket(), param.getStatus(),
                param.getCarriageNum(), param.getRowNum(), param.getSeatNum(), pageQuery.getOffset(), pageQuery.getPageSize());
        return seatList;
    }

    public int countList(TrainSeatSearchParam param) {
        TrainNumber trainNumber = trainNumberMapper.findByName(param.getTrainNumber());
        if (trainNumber == null) {
            throw new BusinessException("待查询的车次不存在");
        }
        return trainSeatMapper.countList(trainNumber.getId(), param.getTicket(), param.getStatus(), param.getCarriageNum(), param.getRowNum(), param.getSeatNum());
    }

    public void generate(GenerateTicketParam param){
        BeanValidator.check(param);
        TrainNumber trainNumber = trainNumberMapper.selectByPrimaryKey(param.getTrainNumberId());
        if (trainNumber == null) {
            throw new BusinessException("该车次不存在");
        }
        List<TrainNumberDetail> detailList = trainNumberDetailMapper.getByTrainNumberId(param.getTrainNumberId());
        if (CollectionUtils.isEmpty(detailList)) {
            throw new BusinessException("该车次无详情");
        }

//        Collections.sort(detailList, Comparator.comparingInt(TrainNumberDetail::getStationIndex));
        //座位类型
        TrainType trainType = TrainType.valueOf(trainNumber.getTrainType());
        //座位配置
        Table<Integer, Integer, Pair<Integer, Integer>> seatTable = TrainTypeSeatConstant.getTable(trainType);

        ZoneId zoneId = ZoneId.systemDefault();

        LocalDateTime localTime = LocalDateTime.parse(param.getFromTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));

        List<TrainSeat> seatList = Lists.newArrayList();
        String ticket = localTime.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        for (TrainNumberDetail detail : detailList) {
            Date fromDate = Date.from(localTime.atZone(zoneId).toInstant());
            Date toDate = Date.from(localTime.plusMinutes(detail.getRelativeMinute()).atZone(zoneId).toInstant());
            Map<Integer, Integer> seatMoneyMap = splitSeatMoney(detail.getMoney());
            //遍历每一节车厢 每一排
            for (Table.Cell<Integer, Integer, Pair<Integer, Integer>> cell : seatTable.cellSet()) {
                //当前车厢，获取座位数及座位等级
                Integer carriage = cell.getRowKey();
                //当前车厢的排，锁定座位数
                Integer row = cell.getColumnKey();
                TrainSeatLevel seatLevel = TrainTypeSeatConstant.getSeatLevel(trainType, carriage);
                Integer money = seatMoneyMap.get(seatLevel.getLevel());
                //获取指定车厢指定排的号的范围
                Pair<Integer, Integer> rowSeatRange = seatTable.get(carriage, row);

                //遍历每一排的每个座位
                for (int index = rowSeatRange.getKey(); index <= rowSeatRange.getValue(); index ++) {
                    //生成座位
                    TrainSeat trainSeat = TrainSeat.builder()
                            .carriageNumber(carriage)
                            .rowNumber(row)
                            .seatNumber(index)
                            .money(money)
                            .ticket(ticket)
                            .seatLevel(seatLevel.getLevel())
                            .trainStart(fromDate)
                            .trainEnd(toDate)
                            .trainNumberId(trainNumber.getId())
                            .showNumber(carriage + "车" + row + "排" + index)
                            .status(0)
                            .fromStationId(detail.getFromStationId())
                            .toStationId(detail.getToStationId())
                            .build();
                    seatList.add(trainSeat);
                }
            }
            localTime = localTime.plusMinutes(detail.getRelativeMinute() + detail.getWaitMinute());
        }
        batchInsertSeat(seatList);
//        trainSeatMapper.batchInsert(seatList);
    }

    @Transactional(rollbackFor = Exception.class)
    public void batchInsertSeat(List<TrainSeat> list) {
        //分批量插入
        List<List<TrainSeat>> trainTicketPartitionList = Lists.partition(list, 1000);

        trainTicketPartitionList.parallelStream()
                .forEach(partitionList -> {
                    //批量插入
                    trainSeatMapper.batchInsert(partitionList);
                });
    }

    private Map<Integer, Integer> splitSeatMoney(String money) {
        //money: 0:100,1:80,2:60
        try {
            List<String> list = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(money);
            Map<Integer, Integer> map = Maps.newHashMap();
            list.forEach(str -> {
                String[] array = str.split(":");
                map.put(Integer.parseInt(array[0]), Integer.parseInt(array[1]));
            });
            return map;
        }catch (Exception e) {
            throw new BusinessException("价钱解析出错!");
        }
    }

    public static void main(String[] args) {
        ZoneId zoneId = ZoneId.systemDefault();
        System.out.println(zoneId);
    }
}
